package com.itheima.mp.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.baomidou.mybatisplus.extension.toolkit.Db;
import com.itheima.mp.domain.dto.PageDTO;
import com.itheima.mp.domain.po.Address;
import com.itheima.mp.domain.po.User;
import com.itheima.mp.domain.query.UserQuery;
import com.itheima.mp.domain.vo.AddressVO;
import com.itheima.mp.domain.vo.UserVO;
import com.itheima.mp.enums.UserStatus;
import com.itheima.mp.mapper.UserMapper;
import com.itheima.mp.service.IUserService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author：余小小
 * @date：2024/7/10
 * @notes：
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
    /**
     * 扣减用户余额
     *
     * @param id
     * @param money 1.查询用户
     *              2.校验用户状态
     *              3.校验余额是否不足
     *              4.扣减余额
     */
    @Override
    @Transactional
    public void deductMoney(Long id, Integer money) {
//        查询用户
        User user = baseMapper.selectById(id);
//        校验用户状态
        if (user == null || user.getStatus() != UserStatus.NORMAL) {
            throw new RuntimeException("用户不存在或状态已冻结");
        }
//        校验余额是否不足
        if (user.getBalance() < money) {
            throw new RuntimeException("余额不足");
        }
//        扣减余额
//        user.setBalance(user.getBalance() - money);
//        baseMapper.updateById(user);

        int remainBalance = user.getBalance() - money;
        lambdaUpdate()
                .set(User::getBalance, remainBalance)
                .set(remainBalance == 0, User::getStatus, 2)
                .eq(User::getId, id)
                .eq(User::getBalance, user.getBalance())
                .update();

        baseMapper.deductBalance(id, money);
    }


    /**
     * 多条件查询所有用户
     *
     * @param name
     * @param status
     **/
    @Override
    public List<User> queryUsers(String name, Integer status, Integer maxBalance, Integer minBalance) {
        List<User> users = lambdaQuery()
                .like(name != null, User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .ge(minBalance != null, User::getBalance, minBalance)
                .le(maxBalance != null, User::getBalance, maxBalance)
                .list();
        return users;
    }

    /**
     * 通过用户id查询用户信息，以及对应的地址信息
     * <p>
     * 1.查询用户
     * 2.查询地址
     *
     * @param id
     * @return
     */
    @Override
    public UserVO queryUserAndAddressById(Long id) {
//        查询用户信息
        User user = this.getById(id);
        if (user == null || user.getStatus() == UserStatus.FROZEN) {
            throw new RuntimeException("用户状态异常！！");
        }
//        查询地址信息集合
        List<Address> addressList = Db.lambdaQuery(Address.class).eq(Address::getUserId, id).list();
//        封装VO
        UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
        if (CollUtil.isNotEmpty(addressList)) {
            userVO.setAddresses(BeanUtil.copyToList(addressList, AddressVO.class));
        }
        return userVO;
    }

    /**
     * 批量查询用户信息
     *
     * @param ids
     * @return
     */

    @Override
    public List<UserVO> queryUserAndAddressByIds(List<Long> ids) {
//        查询用户集合
        List<User> userList = listByIds(ids);
//        获取用户id集合
        List<Long> userIdsList = userList.stream().map(User::getId).collect(Collectors.toList());
//        根据用户id，查询地址
        List<Address> addressList = Db.lambdaQuery(Address.class).in(Address::getUserId, userIdsList).list();
//        转换VO返回
        List<AddressVO> addressVOList = BeanUtil.copyToList(addressList, AddressVO.class);
        Map<Long, List<AddressVO>> addressMap = new HashMap<>();
        if (CollUtil.isNotEmpty(addressVOList)) {
            addressMap = addressVOList.stream().collect(Collectors.groupingBy(AddressVO::getUserId));
        }

        List<UserVO> list = new ArrayList<>(userList.size());
        for (User user : userList) {
            UserVO userVO = BeanUtil.copyProperties(user, UserVO.class);
            list.add(userVO);
//            地址VO
            userVO.setAddresses(addressMap.get(user.getId()));
        }
        return list;
    }


    /**
     * 根据复杂条件分页查询接口实现
     *
     * @param query
     * @return
     */
    @Override
    public PageDTO<UserVO> queryUsersPage(UserQuery query) {
//        1.构建分页条件
        Page<User> page = Page.of(query.getPageNo(), query.getPageSize());
        String name = query.getName();
        Integer status = query.getStatus();
//        排序 默认按照更新时间降序暂时不做
//        if (StrUtil.isEmpty(query.getSortBy())) {
//            page.addOrder(OrderItem.desc("update_time"));
//        }
//        if (query.getIsAsc()) {
//            page.addOrder(OrderItem.asc(query.getSortBy()));
//        }
        if (StrUtil.isNotEmpty(query.getSortBy())) {
            page.addOrder(OrderItem.desc(query.getSortBy()));
        }


//        2.分页查询 使用状态（1正常 2冻结）
        Page<User> userPage = lambdaQuery()
                .like(StrUtil.isNotEmpty(name), User::getUsername, name)
                .eq(status != null, User::getStatus, status)
                .page(page);


//        3.封装VO结果
//        return PageDTO.of(userPage, UserVO.class);
        return PageDTO.of(userPage, user->BeanUtil.copyProperties(user,UserVO.class));
    }

}
